/**
 * 
 */
package com.luck.pf.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;

import com.luck.org.entity.SysMenu;
import com.luck.pf.security.menu.logic.IMenuLogic;
import com.luck.pf.security.menu.qry.MenuQry;

/**
 * 说明: Copyright: Copyright (c) 2010
 * 看看loadResourceDefine方法，我在这里，假定index.jsp和i.jsp这两个资源，需要ROLE_ADMIN角色的用户才能访问。
 * 这个类中，还有一个最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。注意，
 * 我例子中使用的是AntUrlPathMatcher这个path
 * matcher来检查URL是否与资源定义匹配，事实上你还要用正则的方式来匹配，或者自己实现一个matcher。
 * @author zhangwenrui 2010-8-6 下午04:11:06
 * @version 1.0
 */
public class MyInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
	private UrlMatcher urlMatcher = new AntUrlPathMatcher();;
	private IMenuLogic menuLogic;
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
	/**
	 * 读入系统需要过滤的模块，将id,url读入内存
	 */
	public void loadResourceDefine() {
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
		MenuQry qry = new MenuQry();
		qry.setIsInitLoad("1");
		List<SysMenu> menus = menuLogic.findAuthMenu(qry);//得到所有需要过滤的模块
		for(SysMenu m:menus){
			//格式化url
			m.setUrl(filterUrl(m.getUrl()));
			m.setUrl1(filterUrl(m.getUrl1()));
			m.setUrl2(filterUrl(m.getUrl2()));
			//处理主url
			if(StringUtils.isNotBlank(m.getUrl())){
			ConfigAttribute ca = new SecurityConfig(m.getId()+"");
				if (resourceMap.containsKey(m.getUrl())) {
	                Collection<ConfigAttribute> value = resourceMap.get(m.getUrl());
	                value.add(ca);
	                resourceMap.put(m.getUrl(), value);
	            } else {
	                Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
	                atts.add(ca);
	                resourceMap.put(m.getUrl(), atts);
	            }
			}
			//处理url1
			if(StringUtils.isNotBlank(m.getUrl1())){
				ConfigAttribute ca = new SecurityConfig(m.getId()+"");
					if (resourceMap.containsKey(m.getUrl1())) {
		                Collection<ConfigAttribute> value = resourceMap.get(m.getUrl1());
		                value.add(ca);
		                resourceMap.put(m.getUrl1(), value);
		            } else {
		                Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
		                atts.add(ca);
		                resourceMap.put(m.getUrl1(), atts);
		            }
				}
			//处理url2
			if(StringUtils.isNotBlank(m.getUrl2())){
				ConfigAttribute ca = new SecurityConfig(m.getId()+"");
					if (resourceMap.containsKey(m.getUrl2())) {
		                Collection<ConfigAttribute> value = resourceMap.get(m.getUrl2());
		                value.add(ca);
		                resourceMap.put(m.getUrl2(), value);
		            } else {
		                Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
		                atts.add(ca);
		                resourceMap.put(m.getUrl2(), atts);
		            }
				}
		}
	}

	/**
	 * 用户操作每一个url都将根据web.xml的配置来使用url与用户登录时的模块列表来比较
	 */
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		// guess object is a URL.
		String url = ((FilterInvocation) object).getRequestUrl();
		url = filterUrl(url);
		Iterator<String> ite = resourceMap.keySet().iterator();
		while (ite.hasNext()) {
			String resURL = ite.next();
			resURL = filterUrl(resURL);
			if (urlMatcher.pathMatchesUrl(url, resURL)) {
				return resourceMap.get(resURL);
			}
		}
		return null;
	}
	private String filterUrl(String url){
		if(StringUtils.isBlank(url))
			return url;
		if(url.startsWith("/"))
			url = url.substring(1,url.length());
		int i = url.indexOf("?");
		if(i!=-1)
			url = url.substring(0, i);
		return url;
	}
	public boolean supports(Class<?> clazz) {
		return true;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	public IMenuLogic getMenuLogic() {
		return menuLogic;
	}

	public void setMenuLogic(IMenuLogic menuLogic) {
		this.menuLogic = menuLogic;
	}

}
